package com.masonluo.mlonlinejudge.acl.core;

import com.masonluo.mlonlinejudge.acl.core.filter.AuthenticateFilter;
import com.masonluo.mlonlinejudge.acl.core.filter.AuthorizedFilter;
import com.masonluo.mlonlinejudge.acl.core.filter.FilterResult;
import org.springframework.util.CollectionUtils;

import java.util.LinkedList;
import java.util.List;

/**
 * @author masonluo
 * @date 2021/4/17 2:53 下午
 */
public class AuthenticateFilterChain implements AuthorizedFilter {

    private final LinkedList<AuthenticateFilter> authenticateFilterChains = new LinkedList<>();

    private final LinkedList<AuthorizedFilter> authorizedFilterChains = new LinkedList<>();

    @Override
    public FilterResult authenticate(Identification<String> token) {
        // 无需验证登录
        if (CollectionUtils.isEmpty(authenticateFilterChains)) {
            return FilterResult.SUCCESS;
        }
        for (AuthenticateFilter filter : authenticateFilterChains) {
            FilterResult res = filter.authenticate(token);
            if (!res.isSuccess()) {
                return FilterResult.error(res.getErrorMsg(), filter, new Object[]{token});
            }
        }
        return FilterResult.SUCCESS;
    }

    @Override
    public FilterResult authorized(Identification<String> token, List<RoleAccessor> needRoles) {
        // 无需授权
        if (CollectionUtils.isEmpty(authorizedFilterChains)) {
            return FilterResult.SUCCESS;
        }
        // 授权验证，首先需要进行登录
        FilterResult authRes = authenticate(token);
        if (!authRes.isSuccess()) {
            return authRes;
        }
        for (AuthorizedFilter filter : authorizedFilterChains) {
            FilterResult res = filter.authorized(token, needRoles);
            if (!res.isSuccess()) {
                return FilterResult.error(res.getErrorMsg(), filter, new Object[]{token, needRoles});
            }
        }
        return FilterResult.SUCCESS;
    }

    /**
     * 清空所有过滤器
     */
    public void reset() {
        authenticateFilterChains.clear();
        authorizedFilterChains.clear();
    }

    public void addLast(AuthenticateFilter authenticateFilter) {
        authenticateFilterChains.addLast(authenticateFilter);
        if (authenticateFilter instanceof AuthorizedFilter) {
            authorizedFilterChains.addLast((AuthorizedFilter) authenticateFilter);
        }
    }

    public void addFirst(AuthenticateFilter authenticateFilter) {
        authenticateFilterChains.addFirst(authenticateFilter);
        if (authenticateFilter instanceof AuthorizedFilter) {
            authorizedFilterChains.addFirst((AuthorizedFilter) authenticateFilter);
        }
    }

    @Override
    public String toString() {
        return "AuthenticateFilterChain{" +
                "authenticateFilterChains=" + authenticateFilterChains +
                ", authorizedFilterChains=" + authorizedFilterChains +
                '}';
    }
}
